#include <tcp_server.hpp>

TcpServer::TcpServer(int port, TcpServerClient* (*pTcpClientCreator)())
	: TaskRun()
	, m_Running(false)
	, m_MaxClient(16)
	, m_MaxWaitsecs(30)
	, m_ServerSocket(0)
	, m_ServerPort(port)
	, m_TcpClientCreator(pTcpClientCreator)
{
}

TcpServer::~TcpServer()
{
}

void TcpServer::Start(void* arg)
{
	if (m_Running)
	{
		return;
	}

	m_Running = true;

	// TCP协议
	m_ServerSocket = socket(AF_INET, SOCK_STREAM, 0);
	if (m_ServerSocket <= 0)
	{
		LOGE("socket_descriptor error.\n");
		return;
	}

	// 监听所有地址
	struct sockaddr_in bind_addr = { 0 };
	memset(&bind_addr, 0, sizeof(struct sockaddr_in));
	bind_addr.sin_family	  = AF_INET;
	bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	bind_addr.sin_port		  = htons(m_ServerPort);

	// 避免地址和端口上一次使用未结束错误
	int reuseaddr_on = 1;
	if ((setsockopt(m_ServerSocket, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on))) < 0)
	{
		LOGE("setsockopt failed\n");
		return;
	}

	// 绑定服务器端口
	int bind_status = -1;
	for (int i = 0; bind_status == -1 && i < m_MaxWaitsecs; i++)
	{
		bind_status = bind(m_ServerSocket, (struct sockaddr*)&bind_addr, sizeof(struct sockaddr_in));
		if (bind_status == 0)
		{
			break;
		}
		LOGE("Waiting for host port ready... %d/%ds\n", (i + 1), m_MaxWaitsecs);
		TaskRun::mSleep(1000);
	}
	if (bind_status != 0)
	{
		LOGE("Bind host port failed.\n");
		return;
	}

	// 开始监听端口并设置允许接入客户端数量
	int listen_id = listen(m_ServerSocket, m_MaxClient);
	if (listen_id == -1)
	{
		LOGE("Listen host connection.\n");
		return;
	}

	LOGI("TCP Server startup, listen port %d\n", m_ServerPort);
	TaskRun::Start(arg);
}

void TcpServer::Run(void* arg)
{
	while (m_ServerSocket > 0)
	{
		struct sockaddr_in client_address = { 0 };
		socklen_t client_address_length	  = sizeof(struct sockaddr_in);

		// 等待客户端接入
		int socket_id = accept(m_ServerSocket, (struct sockaddr*)&client_address, &client_address_length);
		// 设置缓冲区大小
		SocketSetBuffSize(socket_id, SOCK_BUFF_SIZE, SOCK_BUFF_SIZE);

		// 获取客户端IP
		char client_ip[INET_ADDRSTRLEN] = { 0 };
		inet_ntop(AF_INET, &(client_address.sin_addr), client_ip, INET_ADDRSTRLEN);
		LOGI("Client connected, socketId %d, IP: %s\n", socket_id, client_ip);

		// 创建客户端对象
		TcpServerClient* client = m_TcpClientCreator();
		// 加入到客户端列表中
		m_Clients.push_back(client);
		// 启动客户端
		client->StartRun(client_ip, m_ServerPort, socket_id);

		CleanUp();
	}
}

void TcpServer::CleanUp(void)
{
	for (auto it = m_Clients.begin(); it != m_Clients.end();)
	{
		TcpServerClient* client = *it;
		if (!client->IsRunning())
		{
			it = m_Clients.erase(it);
			delete client;
		}
		else
		{
			it++;
		}
	}
}

void TcpServer::Send(char* data, int size)
{
	if (data == nullptr || size <= 0)
	{
		return;
	}

	for (auto it = m_Clients.begin(); it != m_Clients.end(); it++)
	{
		TcpServerClient* client = *it;
		client->SendData(data, size);
	}
}